import { change2D, change3D, createCoordinateSystem } from '../utils';
import { CSLine, CSLineAttrs } from './CSLine';
import { THREE } from '@amcax/web-render';
export type CSCircleAttrs = {
  startAngle?: number; // 起始角度
  endAngle?: number; // 结束角度
  center?: THREE.Vector3; // 圆心
  radius?: number; // 半径
  clockWise?: boolean; // 顺逆时针
  opacity?: number; // 透明度
  lineWidth?: number;
  maxPoints?: number;
  planeNormal?: THREE.Vector3;
} & Omit<CSLineAttrs, 'vertexs'>;
// 默认点数
const defaultPoints = 25;
export class CSCircle extends CSLine {
  axisCoord: {
    matrix: THREE.Matrix4;
    worldToLocal: THREE.Matrix4;
  };
  segments: number;
  constructor(attrs?: CSCircleAttrs) {
    super({ maxPoints: (attrs.maxPoints ?? defaultPoints) * 2 + 10, ...attrs });
    this.segments = attrs?.maxPoints ?? defaultPoints;
    this.initAttrs(attrs);
  }
  initAttrs(attrs?: CSCircleAttrs) {
    this.userData = { ...attrs };
    if (attrs?.center && attrs?.planeNormal) {
      this.axisCoord = createCoordinateSystem(attrs.center, attrs.planeNormal);
    }
    if (attrs?.radius) {
      this.updateCircle({ radius: attrs.radius, ...attrs });
    }
  }
  updateCircle(attrs?: CSCircleAttrs) {
    this.setUserData(attrs);
    const center = attrs?.center ?? this.userData?.center;
    const radius = attrs?.radius ?? this.userData?.radius;
    const clockWise = attrs.clockWise ?? this.userData?.clockWise;
    const startAngle = attrs?.startAngle ?? this.userData?.startAngle ?? 0;
    const endAngle = attrs?.endAngle ?? this.userData?.endAngle ?? Math.PI * 2;
    const vertexs = this.getCirclePoints(
      center,
      radius,
      clockWise,
      startAngle,
      endAngle,
    );

    attrs?.planeNormal &&
      (this.axisCoord = createCoordinateSystem(center, attrs.planeNormal));
    this.setVertexs(vertexs.map((v) => v.toArray()));
    this.update(attrs);
  }
  setUserData(attrs?: CSCircleAttrs) {
    this.userData = { ...this.userData, ...attrs };
  }
  getCirclePoints(
    center: THREE.Vector3,
    radius: number,
    clockWise: boolean = false,
    startAngle = 0,
    endAngle = 2 * Math.PI,
    num: number = this.segments,
  ) {
    if (!this.axisCoord) {
      return [];
    }

    const cp = change2D(center, this.axisCoord.worldToLocal);
    const shape = new THREE.Shape().absarc(
      cp.x,
      cp.y,
      radius,
      startAngle,
      endAngle,
      clockWise,
    );
    return shape.getPoints(num).map((v) => change3D(v, this.axisCoord.matrix));
  }
  /**
   * 计算圆弧的角度。
   */
  getArcAngle(type: 'deg' | 'rad' = 'deg') {
    const { startAngle = 0, endAngle = 0, clockWise = false } = this.userData;
    // 计算原始差值（考虑方向）
    let delta = clockWise ? startAngle - endAngle : endAngle - startAngle;
    // 归一化到 [0, 2π) 范围
    delta = ((delta % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI);
    return type === 'rad' ? delta : delta * (180 / Math.PI);
  }
  /**
   * 根据给定的弧度或角度值计算圆弧的结束角度。
   */
  getEndPointByRad(rad: number, type: 'deg' | 'rad' = 'deg') {
    if (type === 'deg') {
      rad = THREE.MathUtils.degToRad(rad);
    }
    let endAngle;
    const { startAngle = 0, clockWise = false } = this.userData;
    if (clockWise) {
      endAngle = startAngle - rad; // 顺时针方向：结束角 = 起始角 - 弧度值
    } else {
      endAngle = startAngle + rad; // 逆时针方向：结束角 = 起始角 + 弧度值
    }
    // 归一化到 [0, 2π) 范围
    endAngle = ((endAngle % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI);
    return endAngle;
  }
}
